﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

#if BclAsync40
using static System.Threading.Tasks.TaskEx;
#else
using static System.Threading.Tasks.Task;
#endif

using OmniKits.Extensions;

public static class TextReaderAsyncEx
{
    public static int DefaultBufferSize { get; set; } = 256;
    public const int MinimumBufferSize = 128;

    public static async Task<int> EatAllAsync(this TextReader reader, int bufferSize, bool close = false)
    {
        try
        {
            return await Run(() => reader.EatAll());
        }
        finally
        {
            if (close) reader.Close();
        }
    }
    public static Task<int> EatAllAsync(this TextReader reader, bool close = false)
        => reader.EatAllAsync(DefaultBufferSize, close);

    public static async Task<int> FeedCharsToAsync(this TextReader reader, TextWriter writer, int bufferSize, bool closeReader, bool closeWriter)
    {
        try
        {
            return await Run(() => reader.FeedCharsTo(writer, bufferSize));
        }
        finally
        {
            if (closeReader) reader.Close();
            if (closeWriter) writer.Close();
        }
    }
    public static Task<int> FeedCharsToAsync(this TextReader reader, TextWriter writer, int bufferSize, bool close = false)
        => reader.FeedCharsToAsync(writer, bufferSize, close, close);
    public static Task<int> FeedCharsToAsync(this TextReader reader, TextWriter writer, bool closeReader, bool closeWriter)
        => reader.FeedCharsToAsync(writer, DefaultBufferSize, closeReader, closeWriter);
    public static Task<int> FeedCharsToAsync(this TextReader reader, TextWriter writer, bool close = false)
        => reader.FeedCharsToAsync(writer, DefaultBufferSize, close, close);

    public static async Task<int> FeedAllLinesToAsync(this TextReader reader, TextWriter writer, bool closeReader, bool closeWriter)
    {
        try
        {
            return await Run(() => reader.FeedAllLinesTo(writer));
        }
        finally
        {
            if (closeReader) reader.Close();
            if (closeWriter) writer.Close();
        }
    }
    public static Task<int> FeedAllLinesToAsync(this TextReader reader, TextWriter writer, bool close = false)
        => reader.FeedAllLinesToAsync(writer, close, close);

    public static async Task<int> FeedAllToAsync(this TextReader reader, TextWriter writer, bool closeReader, bool closeWriter)
    {
        try
        {
            return await Run(() => reader.FeedAllTo(writer));
        }
        finally
        {
            if (closeReader) reader.Close();
            if (closeWriter) writer.Close();
        }
    }
    public static Task<int> FeedAllToAsync(this TextReader reader, TextWriter writer, bool close = false)
        => reader.FeedAllToAsync(writer, close, close);

    public static async Task<string> ReadLineWithEndAsync(this TextReader reader, bool close = false)
    {
        try
        {
            return await Run(() => reader.ReadLineWithEnd());
        }
        finally
        {
            if (close) reader.Close();
        }
    }

    public static async Task<int> FeedAllLinesWithEndToAsync(this TextReader reader, TextWriter writer, bool closeReader, bool closeWriter)
    {
        try
        {
            return await Run(() => reader.FeedAllLinesWithEndTo(writer));
        }
        finally
        {
            if (closeReader) reader.Close();
            if (closeWriter) writer.Close();
        }
    }
    public static Task<int> FeedAllLinesWithEndToAsync(this TextReader reader, TextWriter writer, bool close = false)
        => reader.FeedAllLinesWithEndToAsync(writer, close, close);
}
